from eim.tools.dbtool import DBTool
from eim.tools.searchtool import MatchLogic,PartnerRS,SearchCondition,SearchConditionList
from eim.DataBasModals.mode import t_role,t_rs_roleoperate,t_rs_roleuser
from eim.result.page_result import PageResult
from eim.result.simple_result import SimpleResult
from flask import current_app
from sqlalchemy import func,select,update,delete,text,or_,and_,insert,join
from sqlalchemy.engine import LegacyRow,Connection,CursorResult

class RoleService:
    def __init__(self,db):
        """
        构造函数

        Args:
            db (_type_): 数据库操作对象
        """
        self.db=db
        
    def appendNewRole(self,rName:str,rcomment:str)->int:
        """
        添加新的角色

        Args:
            rName (str): 角色名称
            rcomment (str): 角色描述

        Returns:
            int: 新角色的id
        """
        newcode:str=None
        dt:DBTool=None
        try:
            from eim.tools.dbtool import DBTool
            dt = DBTool(self.db)
            newcode = dt.getNewCode('role','R','',6)
            vals ={
                "rcode":newcode,
                "rname":rName,
                "comment": rcomment
            }
            qry = insert(t_role).values(vals)
            con = self.db.engine.connect()
            res:CursorResult=con.execute(qry)
            return res.inserted_primary_key[0]
        except Exception as es:
            if newcode != None:
                dt.returnCode('role','',newcode)
            raise es
        
        
    def upgradeRole(self,id:int,rname:str,rcomment:str="")->int:
        """
        更新角色信息

        Args:
            id (int): 角色编码
            rname (str): 角色名称
            rcomment (str, optional): 角色描述. Defaults to "".

        Returns:
            int: 返回受影响行数
        """
        try:
            vals={
                "rname":rname,
                "comment":rcomment
            }
            qry=update(t_role).values(vals)
            qry=qry.where(t_role.c.ID==id)
            con = self.db.engine.connect()
            res:CursorResult = con.execute(qry)
            return res.rowcount
        except Exception as es:
            raise es
        
    def getOneByID(self,id:int)->dict:
        """
        根据ID获取角色对象

        Args:
            id (_type_): 指定的ID

        Returns:
            dict: 角色对象信息
        """
        try:
            qry = select(t_role).where(t_role.c.ID==id)
            con = self.db.engine.connect()
            res:CursorResult = con.execute(qry)
            r = res.first()
            if(r !=None):
                return r._asdict()
            else:
                raise Exception("指定ID的角色信息不存在")
        except Exception as es:
            raise es
    
    def getOneByCode(self,rcode:str)->dict:
        """
        根据角色编码获取角色信息

        Args:
            rcode (str): 角色编码

        Returns:
            dict: 角色信息
        """
        try:
            qry = select(t_role).where(t_role.c.rcode==rcode)
            con = self.db.engine.connect()
            res:CursorResult = con.execute(qry)
            r = res.first()
            if(r !=None):
                return r._asdict()
            else:
                raise Exception("指定编码的角色信息不存在")
        except Exception as es:
            raise es
    
    def getRoleList(self,pn:int,ps:int)->PageResult:
        """
        分页获取角色信息

        Args:
            pn (int): 分页页码
            ps (int): 分页页面尺寸

        Returns:
            PageResult: 分页结果
        """
        
        try:
            pn = 1 if pn<=0 else pn
            ps = 30 if ps<=0 else ps
            os =(pn-1)*ps
            con = self.db.engine.connect()
            qry_res = select(t_role).limit(ps).offset(os)
            qry_cnt = select(func.count(t_role.c.ID))
            
            records=[]
            res:CursorResult = con.execute(qry_res)
            for row in res.fetchall():
                records.append(row._asdict())
            res=con.execute(qry_cnt)
            total = res.scalar()
            pg = PageResult(pn,ps,total,records).toDict()
            return pg
        except Exception as es:
            raise es
    
    def pageRoles(self,pn:int,ps:int,fields:list,pmlst:SearchConditionList)->dict:
        """
        分页检索角色信息
        Args:
            pn (int): 分页页码
            ps (int): 分页页面尺寸
            fields (list): 查询字段列表
            pmlst (SearchConditionList): 分页查询条件列表类
        Returns:
            dict: 分页结果结构
        """
        try:
            from eim.tools.searchtool import GlobalSearch
            gls=GlobalSearch(self.db)
            pr = gls.pageTableInfo(pn,ps,"role",fields,pmlst);
            return pr
        except Exception as es:
            raise es
            
    def deleteByID(self,id:int)->int:
        """
        删除指定id的角色信息

        Args:
            id (int): 角色id

        Returns:
            int: 受影响行数
        """
        try:
            con = self.db.engine.connect()
            qry = select(func.count(t_rs_roleoperate.c.ID)).join(t_role,t_rs_roleoperate.c.rcode==t_role.c.rcode)
            qry = qry.where(t_role.c.ID==id)
            res:CursorResult = con.execute(qry)
            cnt=res.scalar()
            if(cnt>0):
                raise Exception("角色信息正在被使用,不能删除")
            qry = select(func.count(t_rs_roleuser.c.ID)).join(t_role,t_rs_roleuser.c.rcode==t_role.c.rcode)
            qry= qry.where(t_role.c.ID==id)
            res = con.execute(qry)
            cnt = res.scalar()
            if(cnt>0):
                raise Exception("角色信息正在被使用，不能删除")
            qry=delete(t_role)
            qry=qry.where(t_role.c.ID==id)
            res=con.execute(qry)
            return res.rowcount
        except Exception as es:
            raise
        
    def getAllRoles(self)->list:
        """
        获取所有roles信息

        Returns:
            list: 返回角色列表
        """
        try:
            con = self.db.engine.connect()
            qry=select(t_role.c.rcode,t_role.c.rname,t_role.c.ID)
            cur:CursorResult = con.execute(qry)
            result:list=[]
            for item in cur.fetchall():
                result.append(item._asdict())
            return result
        except Exception as es:
            raise
        
    